<?php
namespace app\index\controller;

use think\Controller;
use think\Request;
use think\Config;
use think\Db;
use think\Db\Query;

class Index extends Controller {
    // use \traits\controller\Jump;
    
    protected $beforeActionList = [
        "index" => ["only" => "view"],
        "about" => ["only" => "view"], // 返回值没有用，只在操作
    ];

    public function _initialize() {
        "https://www.kancloud.cn/manual/thinkphp5/118056";
        // echo "1";
    }

    protected $bgname = '';
    public function __construct($bgname = 'bgname', Request $request) {
        $this->bgname = $bgname;
        parent::__construct();
    }

    public function _empty($name) {
        return $name;
    }

    public function index() {
        echo '1';
        return '<style type="text/css">*{ padding: 0; margin: 0; } .think_default_text{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</style><div style="padding: 24px 48px;"> <h1>:)</h1><p> ThinkPHP V5<br/><span style="font-size:30px">十年磨一剑 - 为API开发设计的高性能框架</span></p><span style="font-size:22px;">[ V5.0 版本由 <a href="http://www.qiniu.com" target="qiniu">七牛云</a> 独家赞助发布 ]</span></div><script type="text/javascript" src="https://tajs.qq.com/stats?sId=9347272" charset="UTF-8"></script><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="ad_bd568ce7058a1091"></think>';
    }

    public function about() {

        Config::set([
            "user" => [
                "type" => 1,
            ]
        ]);

        Config::get("user.type");

        return json(["name"=>"123"]);
    }

    public function view() {
        return $this->fetch('index');
    }

    public function request() {
        $request = Request::instance();
        // 获取当前域名
        echo 'domain: ' . $request->domain() . '<br/>';
        // 获取当前入口文件
        echo 'file: ' . $request->baseFile() . '<br/>';
        // 获取当前URL地址 不含域名
        echo 'url: ' . $request->url() . '<br/>';
        // 获取包含域名的完整URL地址
        echo 'url with domain: ' . $request->url(true) . '<br/>';
        // 获取当前URL地址 不含QUERY_STRING
        echo 'url without query: ' . $request->baseUrl() . '<br/>';
        // 获取URL访问的ROOT地址
        echo 'root:' . $request->root() . '<br/>';
        // 获取URL访问的ROOT地址
        echo 'root with domain: ' . $request->root(true) . '<br/>';
        // 获取URL地址中的PATH_INFO信息
        echo 'pathinfo: ' . $request->pathinfo() . '<br/>';
        // 获取URL地址中的PATH_INFO信息 不含后缀
        echo 'pathinfo: ' . $request->path() . '<br/>';
        // 获取URL地址中的后缀信息
        echo 'ext: ' . $request->ext() . '<br/>';
        echo "当前模块名称是" . $request->module();
        echo "当前控制器名称是" . $request->controller();
        echo "当前操作名称是" . $request->action();
        echo '请求方法：' . $request->method() . '<br/>';
        echo '资源类型：' . $request->type() . '<br/>';
        echo '访问ip地址：' . $request->ip() . '<br/>';
        echo '是否AJax请求：' . var_export($request->isAjax(), true) . '<br/>';
        echo '请求参数：';
        dump($request->param());
        echo '请求参数：仅包含name';
        dump($request->only(['name']));
        echo '请求参数：排除name';
        dump($request->except(['name']));
        echo '路由信息：';
        dump($request->route());
        echo '调度信息：';
        dump($request->dispatch());
    }

    public function param() {
        $request = Request::instance();
        var_dump($request->param('b', 'bb')); // 默认
        var_dump($request->param('a', '', 'strlen')); // 过滤
        var_dump($request->param('a/a'));  // s字符串 d整形 b布尔 a数组 f浮点
    }

    public function isParam() {
        // 是否为 GET 请求
        if (Request::instance()->isGet()) echo "当前为 GET 请求";
        // 是否为 POST 请求
        if (Request::instance()->isPost()) echo "当前为 POST 请求";
        // 是否为 PUT 请求
        if (Request::instance()->isPut()) echo "当前为 PUT 请求";
        // 是否为 DELETE 请求
        if (Request::instance()->isDelete()) echo "当前为 DELETE 请求";
        // 是否为 Ajax 请求
        if (Request::instance()->isAjax()) echo "当前为 Ajax 请求";
        // 是否为 Pjax 请求
        if (Request::instance()->isPjax()) echo "当前为 Pjax 请求";
        // 是否为手机访问
        if (Request::instance()->isMobile()) echo "当前为手机访问";
        // 是否为 HEAD 请求
        if (Request::instance()->isHead()) echo "当前为 HEAD 请求";
        // 是否为 Patch 请求
        if (Request::instance()->isPatch()) echo "当前为 PATCH 请求";
        // 是否为 OPTIONS 请求
        if (Request::instance()->isOptions()) echo "当前为 OPTIONS 请求";
        // 是否为 cli
        if (Request::instance()->isCli()) echo "当前为 cli";
        // 是否为 cgi
        if (Request::instance()->isCgi()) echo "当前为 cgi";
    }

    public function header() {
        var_dump(Request::instance()->header('user-agent'));
    }

    public function suffix() {
        var_dump(Request::instance()->ext());
        var_dump(Request::instance()->get());
    }

    public function hookRequest($name = 'yuan', $user = 'user123') {
        Request::hook('toyouname', 'get_name');
        Request::instance()->toyouname($name);

        Request::instance()->bind('user', $user);
        echo $this->request->user;

        echo $this->bgname;
    }

    public function select() {
        $res = [];
        $res[0] = Db::query('select * from bk_notice where id=:id', ['id'=>1]);
        $res[1] = Db::table('bk_notice')->where('id', 1)->find(); // 不存在返回null
        $res[2] = Db::table('bk_notice')->where('id', 1)->select(); // 不存在返回[]
        $res[3] = Db::name('notice')->find(); // 使用表前缀
        $res[4] = db('notice')->find(); // 助手函数

        $query = new Query();
        $query->name('notice');
        $res[5] = Db::select($query);
        $res[6] = Db::select(function($query) {
            $query->name('notice')->where('id', 1);
        });

        $res[7] = Db::name('notice')->value('title'); // 不存在返回null
        $res[8] = Db::name('notice')->column('id, title'); // 不存在返回[]， 同getField
        $res[9] = Db::name('notice')->chunk(100, function($data) {
            return false; // 中止操作
        }, 'id', 'desc'); // 分批处理
        $res[10] = Db::name('notice')->where('content$.name', 'asan')->find(); // content为json时查name=asan
        var_dump($res);
    }

    public function insert() {
        $data = [];
        Db::name('notice')->insert($data); // 返回成功添加条数
        Db::name('notice')->getListInsId(); // 最后一次添加的ID
        // 或
        Db::name('notice')->insertGetId($data); // 添加并返回主键值

        $data = [[]];
        Db::name('notice')->insertAll($data);
    }

    public function update() {
        $data = [];
        Db::name('notice')->update($data); // 与原版相同写法
        Db::name('notice')->setInc('create_time');
        Db::name('notice')->setDec('create_time', 1, 10); // 返回影响条数, 10秒后操作
        // inc dec exp data 在5.0.5＋可链式操作
    }

    public function delete() {
        Db::name('notice')->delete(2); // 与原版相同
    }

    public function where() {
        Db::name('notice')->where('name|like', 'like', '%thinkphp')
                          ->where('name&title', 'like', ['%thinkphp', 'name%'], 'OR')
                          ->where('id', 'between', [1,8]) // in,not in,between,
                          ->whereOr('name', 'like', '%thinkphp')
                          ->where(function($query) {

                          }) // 混合查询
                          ->where('title',null)
                          ->where('name','not null')
                          ->where('title','=', 'null') // 查询字符串null
                          ->where('name', 'exp', 'IN(1,2,3,4)')
                          ->where('name',['like','thinkphp%'],['like','%thinkphp'], 'or')
                          ->where([
                              // 与原版相同的纯属足条件查询
                          ])
                          ->select(function($query) {
                              // ... 
                          });
        Db::getTableInfo('bk_notice'); // 查看表信息

        $query = new \think\db\Query;
        $query->name('user')
            ->where('name','like','%think%')
            ->where('id','>',10)
            ->limit(10);
        Db::select($query);  

        Db::table('think_user')
                            ->where('name',['like','thinkphp%'],['like','%thinkphp'])
                            ->where(function($query){
                                $query->where('id',['<',10],['>',100],'or');
                            })
                            ->select();
    }

    public function time() {
        Db::name('notice')->where('create_time', '> time', '2016-1-1') // 时间格式任意
                          ->whereTime('create_time', 'between', ['2016-1-1', '2016-2-1'])
                          ->select();

        // 获取今天的博客
        Db::table('think_blog')->whereTime('create_time', 'today')->select();
        // 获取昨天的博客
        Db::table('think_blog')->whereTime('create_time', 'yesterday')->select();
        // 获取本周的博客
        Db::table('think_blog')->whereTime('create_time', 'week')->select();   
        // 获取上周的博客
        Db::table('think_blog')->whereTime('create_time', 'last week')->select();    
        // 获取本月的博客
        Db::table('think_blog')->whereTime('create_time', 'month')->select();   
        // 获取上月的博客
        Db::table('think_blog')->whereTime('create_time', 'last month')->select();      
        // 获取今年的博客
        Db::table('think_blog')->whereTime('create_time', 'year')->select();    
        // 获取去年的博客
        Db::table('think_blog')->whereTime('create_time', 'last year')->select();  

        // 获取今天的博客
        Db::table('think_blog')->whereTime('create_time', 'd')->select();
        // 获取本周的博客
        Db::table('think_blog')->whereTime('create_time', 'w')->select();   
        // 获取本月的博客
        Db::table('think_blog')->whereTime('create_time', 'm')->select();   
        // 获取今年的博客
        Db::table('think_blog')->whereTime('create_time', 'y') ->select();  

        // 查询两个小时内的博客
        Db::table('think_blog')->whereTime('create_time','-2 hours')->select();
    }

    public function pri() {
        // 无说明证明与原版使用方法相同
        Db::name('notice') // table('bk_notice')
            ->where()
            ->alias('n') // 也可以数组键值对形式指定任意表
            ->field('id') // 指定字段，而不是仅查询。可以用在读写操作，说明只局限这几个字段的操作
            ->order('id asc')
            ->limit(1,10) // 读写操作中使用，限制读写的数据条数，使用方式与原版相同
            ->page(1,10) // 分页专用方法，page(页数，数量) 也可以limit指定数量，page指定页数
            ->group('name') // 只能使用字符串指定一个或多个字段
            ->having() // 只能使用字符串，与原生having写法一致
            ->join(['__NOTICE_TYPE__'=>'nt'], ['nt.id＝n.nt_id'], 'INNER')
            ->union(function($query) {

            }) // 合并查询结果
            ->distinct(true) // 返回某个字段的唯一数组，需要在field指定一个字段用以查询
            ->lock(true) // 数据库锁机制
            ->cache('key', 60) // 缓存数据，使用\think\Cache::get('key')获取缓存内容,获取不到返回false
            ->comment('') // 查询注释
            ->fetchSql(true) // 只返回sql, 与 select(false),buildSql() 功能相同，建议使用buildSql子查询
            ->force('title') // 强制使用数据表索引 title 查询
            ->bind(['id'=>[10,\PDO::PARAM_INT],'email'=>'thinkphp@qq.com','name'=>'thinkphp']) // 查询和写入时需要讲字段的实际名称改写为 ':绑定字段名'
            ->strict(true) // 是否开启字段严格检查。全局配置：数据库配置fields_strict
            ->failException(false) // 是否开启空数据报错,true相当于 selectOrFail findOrFail
            ->sequence() // pgsql数据库使用，指定自增序列名
            ->select();

    }

    public function sel() {

        $list = Db::name('notice')
            ->alias('n')
            ->field('n.id,n.title,n.nt_id,nt.name,count(n.id) as countid')
            ->join(['__NOTICE_TYPE__' => 'nt'], ['n.nt_id=nt.id'])
            ->order(['n.id'=>'desc'])
            ->group('nt.id')
            ->having('countid < 5')
            ->limit(1)
            ->page(3)
            ->select();

        // 合并查询内容到主查询上
        $list = Db::name('notice')
            ->where('nt_id', 5)
            ->union(function($query) {
                $query->name('notice')->where('nt_id', 3);
            })
            ->union(function($query) {
                $query->name('notice')->where('nt_id', 4);
            })
            ->cache('union', 60)
            ->select();

        var_dump($list);
    }

    public function cache() {
        $list = \think\Cache::get('union');
        var_dump($list);
        $data1 = Db::name('notice')->field('id,nt_id')->where('id',1)->cache('union')->select([1,2]);
        $data2 = Db::name('notice')->field('id,nt_id')->where('id',1)->cache('union')->update(['nt_id' => 1]); // 指定标识的缓存更新
        $data3 = Db::name('notice')->field('id,nt_id')->where('id',1)->cache('union')->select([1,2]);
        var_dump($data1, $data2, $data3);
    }

    public function bind() {
        $ntId = 3;
        $list = Db::name('notice')->where(['nt_id'=>':nt_id'])->bind(['nt_id'=>$ntId])->select();
        var_dump($list);
    }

    public function failException() {
        $list = Db::name('notice')->where(['nt_id'=>6])->failException(true)->select();
        var_dump($list);
    }

    public function maxin() {
        // 与原版相同
        Db::name('notice')->count();
        Db::name('notice')->max();
        Db::name('notice')->min();
        Db::name('notice')->avg();
        Db::name('notice')->sum();
    }

    /**
     * 视图查询，类比关联数据库
     */
    public function viewd() {
        $list = Db::view(['Notice'=>'notice'], ['id','nt_id'])
            ->view('NoticeType', ['name'], ['notice.nt_id=NoticeType.id'])
            ->select();
        var_dump($list);
    }

    public function buildSql() {
        $bsql = Db::name('notice')->buildSql();
        $list = Db::table($bsql.' a')
            ->where('a.nt_id', 3)
            ->where('a.nt_id', '=', function($query) {
                $query->where('id', 1)->field('nt_id');
            })
            ->where(function($query) {

            }, 'exists')
            ->select();
        var_dump($list);
    }

    /**
     * 原生查询
     */
    public function query() {
        Db::query(''); // 查询
        Db::execute(''); // 更新和写入
        // 问号?和命名占位符
        Db::query('select * from bk_notice where nt_id=?', [3]);
        Db::query('select * from bk_notice where nt_id=:nt_id', ['nt_id'=>3]);
    }

    /**
     * 查询事件 
     * before_find 
     * before_select 
     * after_insert 
     * after_update 
     * after_delete
     * 回调两个参数
     * options 查询配置信息
     * query query查询对象
     */
    public function event() {
        Query::event('before_select', function($options, $query) {
            var_dump($options, $query);
        });
        Db::name('notice')->select();
    }

    /**
     * 事物操作异常回滚
     */
    public function innodb() {
        Db::transaction(function() {
            Db::name('notice')->find(9);
            Db::name('notice')->delete(9);
        });
        // 手动控制
        Db::startTrans();
        try {
            Db::name('notice')->find(9);
            Db::name('notice')->delete(9);
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
        }
    }

    public function listen() {
        Db::listen(function($sql, $time, $explain) {
            echo $sql,' ',$time,'s';
            dump($explain);
        });
        Db::name('notice')->where('id', '>', 2)->select();
    }

    public function sp() {
        $res = Db::query('call sp_query(8)');
        var_dump($res);
    }

    /**
     * 需配置 resultset_type = collection
     */
    public function collection() {
        $list = Db::name('notice')->select();
        $list->isEmpty();
        // isEmpty 是否为空
        // toArray 转换为数组
        // all 所有数据
        // merge   合并其它数据
        // diff    比较数组，返回差集
        // flip    交换数据中的键和值
        // intersect   比较数组，返回交集
        // keys    返回数据中的所有键名
        // pop 删除数据中的最后一个元素
        // shift   删除数据中的第一个元素
        // unshift 在数据开头插入一个元素
        // reduce  通过使用用户自定义函数，以字符串返回数组
        // reverse 数据倒序重排
        // chunk   数据分隔为多个数据块
        // each    给数据的每个元素执行回调
        // filter  用回调函数过滤数据中的元素
        // column  返回数据中的指定列
        // sort    对数据排序
        // shuffle 将数据打乱
        // slice   截取数据中的一部分
        var_dump($list);
    }

}
